package com.atmilan.quartz.sync.pull.europe.service.impl;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeSet;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestTemplate;

import com.alibaba.fastjson.JSONObject;
import com.atmilan.quartz.constant.enums.UpdateFlagEnum;
import com.atmilan.quartz.model.entity.europe.EuropeProduct;
import com.atmilan.quartz.model.entity.europe.EuropeProductSku;
import com.atmilan.quartz.model.entity.europe.EuropeProductSkuMerged;
import com.atmilan.quartz.sync.pull.europe.mapper.EuropeProductMapper;
import com.atmilan.quartz.sync.pull.europe.service.IEuropeProductService;
import com.atmilan.quartz.sync.pull.europe.service.IEuropeProductSkuMergedService;
import com.atmilan.quartz.sync.pull.europe.service.IEuropeProductSkuService;
import com.atmilan.quartz.utils.EuropeSendXmlUtil;
import com.atmilan.quartz.utils.EuropeUtil;
import com.atmilan.quartz.utils.STAXUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class EuropeProductServiceImpl extends ServiceImpl<EuropeProductMapper, EuropeProduct> implements IEuropeProductService {
    ExecutorService service = Executors.newFixedThreadPool(25);
    @Value("${europe.url}")
    private String url;
    @Value("${europe.username}")
    private String username;
    @Value("${europe.password}")
    private String password;
    private final String xmlGoods = "<tem:GetGoodsListByPage><tem:PageNum>{}</tem:PageNum><tem:PageSize>{}</tem:PageSize></tem:GetGoodsListByPage>";

    @Autowired
    IEuropeProductService europeProductService;
    @Autowired
    IEuropeProductSkuService europeProductSkuService;
    @Autowired
    IEuropeProductSkuMergedService europeProductSkuMergedService;
    @Autowired
    EuropeProductMapper europeProductMapper;
    @Autowired
    EuropeUtil europeUtil;

    Lock lock = new ReentrantLock();

    @Override
    public void getGoods() {
        if (lock.tryLock()) {
            try {
                long millis = System.currentTimeMillis();
                beforeProcess();
                log.info("--------------- 欧洲商品拉取数据, 初始化集合用时: {}秒---------------", (System.currentTimeMillis() - millis) / 1000);
                millis = System.currentTimeMillis();
                getGoodsList(1, 300, username, password, url);
                log.info("--------------- 欧洲商品拉取数据, 同步完成用时: {}秒---------------", (System.currentTimeMillis() - millis) / 1000);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    }


    // 合并sku数据
    public void updateSkuMerged(List<EuropeProductSku> skuList) {
        if (!CollectionUtils.isEmpty(skuList)) {
            Map<String, Integer> sumStockMap = skuList.stream().collect(Collectors.groupingBy(c -> c.getAttrKey(), Collectors.summingInt(EuropeProductSku::getQty)));

            // 过滤掉 size 空的数据，库存按size汇总，去重
            skuList = skuList.stream().filter(sku -> StringUtils.isNotBlank(sku.getAttrKey() + sku.getSize())).map(sku -> sku.setQty(sumStockMap.get(sku.getAttrKey()))).collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(EuropeProductSku::getAttrKey))), ArrayList::new));

            skuList.forEach(sku -> {
                EuropeProductSkuMerged skuMerged = europeProductSkuMergedService.toMergedModel(sku);
                skuMerged.setEditTime(DateUtil.date());
                skuMerged.setUpdateFlag(UpdateFlagEnum.add.getCode());
                EuropeProductSkuMerged europeProductSkuMergedDb = europeProductSkuMergedService.getOne(Wrappers.<EuropeProductSkuMerged>lambdaQuery()
                        .eq(EuropeProductSkuMerged::getGoodsId, skuMerged.getGoodsId())
                        .eq(EuropeProductSkuMerged::getColor, skuMerged.getColor())
                        .eq(EuropeProductSkuMerged::getSize, skuMerged.getSize())
                        );
                if (null != europeProductSkuMergedDb) {
                    skuMerged.setEditTime(new Date());
                    europeProductSkuMergedService.update(skuMerged, Wrappers.<EuropeProductSkuMerged>lambdaUpdate().eq(EuropeProductSkuMerged::getGoodsId, skuMerged.getGoodsId()).eq(EuropeProductSkuMerged::getColor, skuMerged.getColor()).eq(EuropeProductSkuMerged::getSize, skuMerged.getSize()));
                } else {
                    skuMerged.setCreateTime(DateUtil.date());
                    europeProductSkuMergedService.save(skuMerged);
                }
            });
        }
    }

    private void beforeProcess() {
        europeProductService.update(Wrappers.<EuropeProduct>lambdaUpdate().set(EuropeProduct::getUpdateFlag, UpdateFlagEnum.un_modify.getCode()));
        europeProductSkuService.update(Wrappers.<EuropeProductSku>lambdaUpdate().set(EuropeProductSku::getUpdateFlag, UpdateFlagEnum.un_modify.getCode()));
        europeProductSkuMergedService.update(Wrappers.<EuropeProductSkuMerged>lambdaUpdate().set(EuropeProductSkuMerged::getUpdateFlag, UpdateFlagEnum.un_modify.getCode()));
    }


    public Boolean saveGoods(List<Map<String, Object>> europMapList) {
        if (CollectionUtils.isEmpty(europMapList)) {
            return false;
        }
        //解析xml文档
        List<EuropeProduct> goodList = new ArrayList<>();
        for (Map<String, Object> map : europMapList) {
            service.execute(() -> {
                try {
                    //商品价格和库存小于等于零则不保存数据
                    BigDecimal price = new BigDecimal((String) map.get("Price"));
                    //判断此商品是否有sku，没有则不用保存数据
                    String goodsId = (String) map.get("ID");
                    // 调用第三方接口查询商品sku, 并且保存数据
                    List<EuropeProductSku> productSkus = getEuropeProductSkus(goodsId);
                    EuropeProduct europeGood = new EuropeProduct();
                    // 设置更新标志, 最终为0 的都是本次未同步到的数据
                    europeGood.setUpdateFlag(UpdateFlagEnum.add.getCode());
                    europeGood = getEuropeProduct(europeGood, map, price, productSkus);
                    goodList.add(europeGood);
                    EuropeProduct europeProductDb = europeProductService.getOne(Wrappers.<EuropeProduct>lambdaQuery()
                            .eq(EuropeProduct :: getGoodId, map.get("ID")+"")
                            .last("LIMIT 1"));
                    if (null != europeProductDb) {
                        europeGood.setNewModifyTime(DateUtil.date());
                        europeProductService.updateById(europeGood);
                    } else {
                        europeGood.setNewCreatedTime(DateUtil.date());
                        europeProductService.save(europeGood);
                    }
                    //更新SKU
                    List<EuropeProductSku> skuList = europeProductSkuService.getEuropeProductSkuListByGoodsId(europeGood.getGoodId() + "");
                    updateSkuMerged(skuList);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
        }
        return false;
    }

    public EuropeProduct getEuropeProduct(EuropeProduct europeGood, Map<String, Object> map, BigDecimal price, List<EuropeProductSku> productSkus) {
        europeGood.setGoodId(Integer.parseInt((String) map.get("ID")));
        europeGood.setModel((String) map.get("Model"));
        europeGood.setVariante((String) map.get("Variante"));
        europeGood.setSeason((String) map.get("Season"));
        europeGood.setCollection((String) map.get("Collection"));
        europeGood.setSupplierId(Integer.parseInt((String) map.get("SupplierID")));
        europeGood.setBrandId(Integer.parseInt((String) map.get("BrandID")));
        europeGood.setParentCategoryId(Integer.parseInt((String) map.get("ParentCategoryID")));
        europeGood.setCategoryId(Integer.parseInt((String) map.get("CategoryID")));
        europeGood.setTypeId(Integer.parseInt((String) map.get("TypeID")));
        europeGood.setCode((String) map.get("Code"));
        europeGood.setGoodsName((String) map.get("GoodsName"));
        europeGood.setReferencePrice(new BigDecimal((String) map.get("ReferencePrice")));
        europeGood.setPrice(price);
        europeGood.setDiscount((String) map.get("Discount"));
        europeGood.setStock(Integer.parseInt((String) map.get("Stock")));
        europeGood.setMainPicNo((String) map.get("MainPicNo"));
        //获取商品sku的缩略图和商品相册
        if (productSkus != null && productSkus.size() > 0) {
            if (StringUtils.isNotBlank(productSkus.get(0).getPictures())) {
                List<Map> lists = JSONObject.parseArray(productSkus.get(0).getPictures(), Map.class);
                List<Map<String, Object>> list = new ArrayList<>();
                lists.forEach(vo -> {
                    Map<String, Object> map1 = new HashMap<>();
                    map1.put("img_original", (String) vo.get("PictureUrl"));
                    map1.put("thumb_url", vo.get("PictureThumbUrl"));
                    list.add(map1);
                });
                europeGood.setGallery(JSONObject.toJSONString(list));
                if (!CollectionUtils.isEmpty(lists)) {
                    europeGood.setGoodsImg((String) lists.get(0).get("PictureUrl"));
                }
            } else {
                europeGood.setGallery("");
                europeGood.setGoodsImg("");
            }
        } else {
            europeGood.setGallery("");
            europeGood.setGoodsImg("");
        }

        try {
            String oldCreatedTime = (String) map.get("CreatedTime");
            if (oldCreatedTime != null && StringUtils.isNotBlank(oldCreatedTime)) {
                if (oldCreatedTime.endsWith("AM")) {
                    oldCreatedTime = oldCreatedTime.replace(" AM", "");
                    europeGood.setOldCreatedTime(new SimpleDateFormat("MM/dd/yyyy HH:mm:ss").parse(oldCreatedTime));//map.get("CreatedTime")
                } else {
                    oldCreatedTime = oldCreatedTime.replace(" PM", "");
                    europeGood.setOldCreatedTime(new SimpleDateFormat("MM/dd/yyyy HH:mm:ss").parse(oldCreatedTime));//map.get("CreatedTime")
                }
            } else {
                europeGood.setOldCreatedTime(null);
            }
            String oldModifyTime = (String) map.get("ModifyTime");
            if (oldModifyTime != null && StringUtils.isNotBlank(oldModifyTime)) {
                if (oldModifyTime.endsWith("AM")) {
                    oldModifyTime = oldModifyTime.replace(" AM", "");
                    europeGood.setOldModifyTime(new SimpleDateFormat("MM/dd/yyyy HH:mm:ss").parse(oldModifyTime));
                } else {
                    oldModifyTime = oldModifyTime.replace(" PM", "");
                    europeGood.setOldModifyTime(new SimpleDateFormat("MM/dd/yyyy HH:mm:ss").parse(oldModifyTime));
                }
            } else {
                europeGood.setOldModifyTime(null);
            }
        } catch (Exception e) {

        }
        return europeGood;
    }

    private void getGoodsList(Integer pageNum, Integer pageSize, String username, String password, String url) throws Exception {
        int remotePageCount = 1;
        String auth = Base64.encode((username + ":" + password).getBytes());

        while (remotePageCount > 0) {
            Long start = System.currentTimeMillis();

            String msg = EuropeSendXmlUtil.getSendMsg(StrUtil.format(xmlGoods, pageNum, pageSize));
            String respXml = europeUtil.getEuropeXmlNew(auth, url, msg);
            if (StrUtil.isEmpty(respXml)) {
                log.info("--------------- 获取到报文, 页数: {}, 查询到: {}条 ---------------", pageNum, remotePageCount);
                pageNum++;
                continue;
            }

            List<Map<String, Object>> europMapList = STAXUtil.getEuropMapList(respXml, "GetGoodsListByPage");
            remotePageCount = europMapList.size();
            Long now = System.currentTimeMillis();
            log.info("--------------- 执行欧洲商品远程查询, 页数: {}, 查询到: {}条, 耗时: {}秒---------------", pageNum, remotePageCount, (now - start) / 1000);
            saveGoods(europMapList);
            log.info("--------------- 保存欧洲商品, 耗时: {}秒---------------", (System.currentTimeMillis() - now));

            pageNum++;
        }
    }

    public List<String> allGoodsIdList() {
        List<Object> list = europeProductMapper.selectObjs(new QueryWrapper<EuropeProduct>().select("good_id"));
        return list == null ? new ArrayList<String>() : list.stream().map(o -> o.toString()).collect(Collectors.toList());
    }

    public List<EuropeProductSku> getEuropeProductSkus(String goodsId) {
        String xml = "<tem:GetGoodsDetailByGoodsID><tem:GoodsID>" + goodsId + "</tem:GoodsID></tem:GetGoodsDetailByGoodsID>";
        String auth = Base64.encode((username + ":" + password).getBytes());
        //调用接口
        String sendMsg = EuropeSendXmlUtil.getSendMsg(xml);
        try {
            String respXml = europeUtil.getEuropeXmlNew(auth, url, sendMsg);
            List<Map<String, Object>> europMapList = STAXUtil.getEuropMapList(respXml, "GetGoodsDetailByGoodsID");
            //解析数据
            List<EuropeProductSku> productSkuList = saveProductSku(europMapList);
            return productSkuList;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    private List<EuropeProductSku> saveProductSku(List<Map<String, Object>> europMapList) {
        //根据goodsId查询只有一条数据
        Map<String, Object> map = europMapList.get(0);
        List<EuropeProductSku> list = new ArrayList<>();
        //获取sku库存
        List<HashMap<String, Object>> stockList = (List<HashMap<String, Object>>) map.get("Stock");

        stockList.forEach(item -> {
            EuropeProductSku europeProductSku = new EuropeProductSku();
            europeProductSku.setUpdateFlag(UpdateFlagEnum.add.getCode());

            int qty = Integer.parseInt((String) item.get("Qty"));
            getEuropeProductSku(qty, europeProductSku, map, item, stockList);
            //判断是新增还是更新
            EuropeProductSku europeProductSkuDb = europeProductSkuService.getById(europeProductSku.getId());
            if (null != europeProductSkuDb) {//修改
                europeProductSku.setNewModifyTime(new Date());
            } else {
                europeProductSku.setNewCreatedTime(DateUtil.date());
            }
            europeProductSkuService.saveOrUpdate(europeProductSku);
            list.add(europeProductSku);
        });
        return list;
    }

    private EuropeProductSku getEuropeProductSku(int qty, EuropeProductSku europeProductSku, Map<String, Object> map, HashMap<String, Object> item, List<HashMap<String, Object>> stockList) {
        europeProductSku.setId((String) map.get("ID") + "-" + stockList.indexOf(item));
        europeProductSku.setGoodsId(Integer.parseInt((String) map.get("ID")));
        europeProductSku.setSuperColor((String) map.get("SuperColor"));
        europeProductSku.setColor((String) map.get("Color"));
        europeProductSku.setFabric((String) map.get("Fabric"));
        europeProductSku.setComposition((String) map.get("Composition"));
        europeProductSku.setSizeAndFit((String) map.get("SizeAndFit"));
        europeProductSku.setMadeIn((String) map.get("MadeIn"));

        if (StringUtils.isNotBlank(map.get("Pictures").toString())) {
            List<HashMap<String, Object>> pictures = (List<HashMap<String, Object>>) map.get("Pictures");
            europeProductSku.setPictures(JSONObject.toJSONString(pictures));
        }
        if (StringUtils.isNotBlank(map.get("Stock").toString())) {
            List<HashMap<String, Object>> stock = (List<HashMap<String, Object>>) map.get("Stock");
            europeProductSku.setStock(JSONObject.toJSONString(stock));
        }
        europeProductSku.setSize((String) item.get("Size"));
        europeProductSku.setQty(qty);
        europeProductSku.setSuk((String) map.get("Color") + "," + (String) item.get("Size"));
        String oldCreatedTime = (String) map.get("CreatedTime");
        if (oldCreatedTime != null && StringUtils.isNotBlank(oldCreatedTime)) {
            if (oldCreatedTime.endsWith("AM")) {
                oldCreatedTime = oldCreatedTime.replace(" AM", "");
                try {
                    europeProductSku.setOldCreatedTime(new SimpleDateFormat("MM/dd/yyyy HH:mm:ss").parse(oldCreatedTime));
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            } else {
                oldCreatedTime = oldCreatedTime.replace(" PM", "");
                try {
                    europeProductSku.setOldCreatedTime(new SimpleDateFormat("MM/dd/yyyy HH:mm:ss").parse(oldCreatedTime));
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            }
        } else {
            europeProductSku.setOldCreatedTime(null);
        }
        String oldModifyTime = (String) map.get("ModifyTime");
        if (oldModifyTime != null && StringUtils.isNotBlank(oldModifyTime)) {
            if (oldModifyTime.endsWith("AM")) {
                oldModifyTime = oldModifyTime.replace(" AM", "");
                try {
                    europeProductSku.setOldModifyTime(new SimpleDateFormat("MM/dd/yyyy HH:mm:ss").parse(oldModifyTime));
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            } else {
                oldModifyTime = oldModifyTime.replace(" PM", "");
                try {
                    europeProductSku.setOldModifyTime(new SimpleDateFormat("MM/dd/yyyy HH:mm:ss").parse(oldModifyTime));
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            }
        } else {
            europeProductSku.setOldModifyTime(null);
        }

        return europeProductSku;
    }

    @Override
    public void deleteAll() {
        europeProductMapper.deleteAll();
    }

    @Override
    public void copyAll() {
        europeProductMapper.deleteProductBack();
        europeProductMapper.copyProductBack();
    }
    
}
